﻿using System;
using System.IO;
using System.Collections;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using UnityEngine;

public unsafe class Libc  {
    public static FILE stdout;
    public static void fseek(FILE File, uint offset, SeekOrigin origin)
    {
        File.file.Seek(offset, origin);
    }
    public static void free(object o)
    {

    }
    public static void free(void * o)
    {

    }
    public static void* getBytePtr(byte[] d)
    {
        IntPtr intptr = Marshal.UnsafeAddrOfPinnedArrayElement(d, 0);
        return (void*)intptr;
    }
    public static void* malloc(long v)
    {
       // IntPtr intptr = Marshal.AllocHGlobal(Marshal.SizeOf(vga));

        IntPtr intptr = Marshal.UnsafeAddrOfPinnedArrayElement(new byte[v], 0);
        return (void*)intptr;
    }

    public static app_import_entry realloc(app_import_entry[] import_data, long v)
    {
        throw new NotImplementedException();
    }

    public static FILE fopen(string name, string mode)
    {
        FILE file = new FILE();
        FileStream fileStream = new FileStream(name, (FileMode.Open));
        file.file = fileStream;
        return file;
    }

    public static ushort ftell(FILE tempFile)
    {
        return (ushort)tempFile.file.Length;
    }

    public static void fprintf(FILE fp, string v1, uint v2=0)
    {
       
    }

    public static int fread(void* data, long count, int offset, FILE tempFile)
    {
        byte* d = (byte*)data;
        for (int i = 0; i < count; i++)
        {
            d[i + offset - 1] = (byte)tempFile.file.ReadByte();
        }
        return (int)count;
    }

    public static uint fwrite(void* data, uint offset, uint count, FILE inStream)
    {
        byte* d = (byte*)data;
        for (int i = 0; i < count; i++)
        {
            inStream.file.WriteByte(d[i + offset - 1]);
        }
        return count;
    }

    public static void fwrite(char inString, int v, int tempLen, FILE inStream)
    {

    }

    public static string toString(void* s)
    {
        return new string((sbyte *)s);
    }

    public static void* memcpy(void* dst, void* src, long size)
    {
        if (size < 0)
        {
            Debug.LogError("memcpy size miss");
        }
        byte* psrc;
        byte* pdst;

        if (null == dst || null == src)
        {
            return null;
        }

        if ((src < dst) && (byte*)src + size > (byte*)dst) // 自后向前拷贝
        {
            psrc = (byte*)src + size - 1;
            pdst = (byte*)dst + size - 1;
            while (size-- != 0)
            {
                *pdst-- = *psrc--;
            }
        }
        else
        {
            psrc = (byte*)src;
            pdst = (byte*)dst;
            while (size-- != 0)
            {
                *pdst++ = *psrc++;
            }
        }

        return dst;
    }
    public static void* memset(void* bin_data, int v, long length)
    {
        byte* d = (byte*)bin_data;
        for (int i = 0; i < length; i++)
        {
            *d = (byte)v;
        }
        return bin_data;
    }
    public static void* memset(void* bin_data, uint v, long length)
    {
        memset(bin_data, (int)v, length);
        return bin_data;
    }
    public static string _errno()
    {
        return "errno";
    }

    public static void GetSystemTimeAsFileTime(FILETIME ft)
    {

    }
    public static uint GetCurrentThreadId()
    {
        return 0;
    }

    public static uint sem_wait(sem_t sem)
    {
        return sem.id;
    }

    public static uint sem_post(sem_t sem)
    {
        return sem.id;
    }

    public class FILE
    {
        public FileStream file;

        public void Read()
        {

        }
    }

    public class FILETIME
    {
        internal ulong dwHighDateTime;
        internal ulong dwLowDateTime;
    }

    public class Debug
    {
        internal static void Assert(int v)
        {
            UnityEngine.Debug.Assert(v != 0);
        }

        internal static void LogError(string v)
        {
            UnityEngine.Debug.LogError(v);
        }
    }

    public static SeekOrigin SEEK_SET = SeekOrigin.Begin;
    public static SeekOrigin SEEK_END = SeekOrigin.End;
    public static SeekOrigin SEEK_CUR = SeekOrigin.Current;
}

public struct sem_t
{
   public uint id;
}

public class pthread_t
{

}
